from flask_apscheduler import APScheduler
import requests
import json
from datetime import datetime, timedelta
import pymysql
from config import Config
from typing import Dict, Any, Optional
import logging

# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

scheduler = APScheduler()

def get_db():
    return pymysql.connect(
        host=Config.MYSQL_HOST,
        port=Config.MYSQL_PORT,
        user=Config.MYSQL_USER,
        password=Config.MYSQL_PASSWORD,
        db=Config.MYSQL_DB,
        charset='utf8mb4',
        cursorclass=pymysql.cursors.DictCursor
    )

def get_wechat_token() -> str:
    """获取企业微信访问令牌"""
    url = f'https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={Config.WECHAT_CORP_ID}&corpsecret={Config.WECHAT_CORP_SECRET}'
    response = requests.get(url)
    response.raise_for_status()
    return response.json()['access_token']

def send_wechat_message(user_id: str, content: str) -> None:
    """发送企业微信消息"""
    try:
        token = get_wechat_token()
        url = f'https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token={token}'
        data = {
            "touser": user_id,
            "msgtype": "text",
            "agentid": Config.WECHAT_AGENT_ID,
            "text": {
                "content": content
            }
        }
        response = requests.post(url, json=data)
        response.raise_for_status()
    except Exception as e:
        logger.error(f"发送企业微信消息失败: {str(e)}")

@scheduler.task('cron', id='fetch_fund_net_values', hour='15', minute='30')
def fetch_fund_net_values() -> None:
    """每天15:30获取基金净值"""
    try:
        with get_db() as conn:
            with conn.cursor() as cursor:
                # 获取所有基金
                cursor.execute('SELECT id, code FROM funds')
                funds = cursor.fetchall()
                
                for fund in funds:
                    try:
                        # 获取基金净值
                        response = requests.get(Config.FUND_API_URL.format(fund['code']))
                        response.raise_for_status()
                        data = response.text
                        
                        # 解析净值数据
                        unit_value = float(data.split('fS_dwjz = "')[1].split('"')[0])
                        total_value = float(data.split('fS_ljjz = "')[1].split('"')[0])
                        
                        # 保存净值
                        cursor.execute('''
                            INSERT INTO fund_net_values (fund_id, date, unit_value, total_value)
                            VALUES (%s, %s, %s, %s)
                            ON DUPLICATE KEY UPDATE
                            unit_value = VALUES(unit_value),
                            total_value = VALUES(total_value)
                        ''', (fund['id'], datetime.now().date(), unit_value, total_value))
                        conn.commit()
                    except Exception as e:
                        logger.error(f"获取基金 {fund['code']} 净值失败: {str(e)}")
                        continue
    except Exception as e:
        logger.error(f"获取基金净值任务失败: {str(e)}")

@scheduler.task('cron', id='check_monitor_rules', hour='15', minute='35')
def check_monitor_rules() -> None:
    """每天15:35检查监控规则"""
    try:
        with get_db() as conn:
            with conn.cursor() as cursor:
                # 获取所有活跃的监控规则
                cursor.execute('''
                    SELECT mr.*, f.code, f.name, u.wechat_user_id
                    FROM monitor_rules mr
                    JOIN funds f ON mr.fund_id = f.id
                    JOIN users u ON mr.user_id = u.id
                    WHERE mr.is_active = TRUE
                ''')
                rules = cursor.fetchall()
                
                for rule in rules:
                    try:
                        # 获取最新净值
                        cursor.execute('''
                            SELECT unit_value, total_value
                            FROM fund_net_values
                            WHERE fund_id = %s
                            ORDER BY date DESC
                            LIMIT 1
                        ''', (rule['fund_id'],))
                        latest_value = cursor.fetchone()
                        
                        if not latest_value:
                            continue
                        
                        # 根据规则类型检查
                        if rule['rule_type'] == 'rate':
                            # 检查收益率
                            cursor.execute('''
                                SELECT unit_value
                                FROM fund_net_values
                                WHERE fund_id = %s
                                AND date = %s
                            ''', (rule['fund_id'], rule['start_date']))
                            start_value = cursor.fetchone()
                            
                            if start_value:
                                rate = (latest_value['unit_value'] - start_value['unit_value']) / start_value['unit_value'] * 100
                                if rate >= rule['threshold']:
                                    send_wechat_message(
                                        rule['wechat_user_id'],
                                        f"基金{rule['code']}({rule['name']})已达到预期收益率{rule['threshold']}%，当前收益率{rate:.2f}%"
                                    )
                        
                        elif rule['rule_type'] == 'drop':
                            # 检查跌幅
                            cursor.execute('''
                                SELECT unit_value
                                FROM fund_net_values
                                WHERE fund_id = %s
                                AND date = %s
                            ''', (rule['fund_id'], rule['start_date']))
                            start_value = cursor.fetchone()
                            
                            if start_value:
                                drop_rate = (start_value['unit_value'] - latest_value['unit_value']) / start_value['unit_value'] * 100
                                if drop_rate >= rule['threshold']:
                                    send_wechat_message(
                                        rule['wechat_user_id'],
                                        f"基金{rule['code']}({rule['name']})跌幅超过{rule['threshold']}%，当前跌幅{drop_rate:.2f}%"
                                    )
                        
                        elif rule['rule_type'] == 'date':
                            # 检查是否达到指定日期净值
                            cursor.execute('''
                                SELECT unit_value
                                FROM fund_net_values
                                WHERE fund_id = %s
                                AND date = %s
                            ''', (rule['fund_id'], rule['start_date']))
                            target_value = cursor.fetchone()
                            
                            if target_value and abs(latest_value['unit_value'] - target_value['unit_value']) / target_value['unit_value'] <= 0.01:
                                send_wechat_message(
                                    rule['wechat_user_id'],
                                    f"基金{rule['code']}({rule['name']})已达到目标净值{target_value['unit_value']:.4f}"
                                )
                    except Exception as e:
                        logger.error(f"检查监控规则 {rule['id']} 失败: {str(e)}")
                        continue
    except Exception as e:
        logger.error(f"检查监控规则任务失败: {str(e)}")

def init_scheduler(app):
    """初始化调度器"""
    scheduler.init_app(app)
    scheduler.start() 